#pragma once
#include "LPDef.h"

namespace LocalProxy{
#pragma warning(push)
#pragma warning(disable:4996 )

	class CHTTPHeaderLine
	{
	public:
		static BOOL IsHeaderLine(const CString &sLine,CString &sName,CString &sConent)
		{
			const int iSplit=sLine.Find(_T(':'));
			if(iSplit==-1)
			{
				return FALSE;
			}
			sName=sLine.Mid(0,iSplit).Trim();
			sConent=sLine.Mid(iSplit+1).Trim();
			return TRUE;
		}

		CHTTPHeaderLine(const CString &sName,const CString &sContent)
			:m_sName(sName)
			,m_sContent(sContent)
		{
		}

		CHTTPHeaderLine(const CHTTPHeaderLine &other)
			:m_sName(other.m_sName)
			,m_sContent(other.m_sContent)
		{

		}

		LPCTSTR Name() const
		{
			return m_sName;
		}

		LPCTSTR Content() const
		{
			return m_sContent;
		}

		CStringA GetLine() const
		{
			return CStringA(m_sName+_T(": ")+m_sContent);
		}
	protected:
		CString m_sName;
		CString m_sContent;
	};

	class CHTTPHeaderHost
		:public CHTTPHeaderLine
	{
	public:
		static BOOL Match(const CString &sHeaerName)
		{
			return StrCmpI(sHeaerName,_T("Host"))==0;
		}

		CHTTPHeaderHost(const CString &sHost)
			:CHTTPHeaderLine(_T("Host"),sHost)
		{}

		CHTTPHeaderHost(const CHTTPHeaderLine &other)
			:CHTTPHeaderLine(other)
		{}

		LPCTSTR GetHost() const
		{
			return m_sContent;
		}

		void SetHost(const CString &sHost)
		{
			m_sContent=sHost;
		}
	};

	class CHTTPHeaderConnection
		:public CHTTPHeaderLine
	{
	public:		
		static const TCHAR *ConnectionTypeStr[];
		static BOOL Match(const CString &sHeaerName)
		{
			return StrCmpI(sHeaerName,_T("Connection"))==0;
		}
		CHTTPHeaderConnection(ConnectionType t)
			:CHTTPHeaderLine(_T("Connection"),CTToStr(t))
			,m_ct(t)
		{}

		CHTTPHeaderConnection(const CString &sCT)
			:CHTTPHeaderLine(_T("Connection"),sCT)
			,m_ct(StrToCT(sCT))
		{}

		CHTTPHeaderConnection(const CHTTPHeaderLine &other)
			:CHTTPHeaderLine(other)
			,m_ct(StrToCT(other.Content()))
		{}

		
		ConnectionType GetConnection() const
		{
			return StrToCT(m_sContent);
		}

		void SetConnection(ConnectionType t)
		{			
			m_sContent=CTToStr(t);
		}
	private:
		static ConnectionType StrToCT(LPCTSTR s)
		{
			if(StrCmpI(s,ConnectionTypeStr[CT_Close])==0)
				return CT_Close;
			if(StrCmpI(s,ConnectionTypeStr[CT_Keep_Alive])==0)
				return CT_Keep_Alive;
			ATLASSERT(0);
			return CT_Unknow;
		}

		static LPCTSTR CTToStr(ConnectionType ct)
		{
			switch(ct)
			{
			case CT_Close:
				return ConnectionTypeStr[CT_Close];
			case CT_Keep_Alive:
				return ConnectionTypeStr[CT_Keep_Alive];
			default:
				ATLASSERT(0);
				return ConnectionTypeStr[CT_Unknow]; 
			}
		}
		ConnectionType m_ct;
	};
	__declspec(selectany)
		const TCHAR *CHTTPHeaderConnection::ConnectionTypeStr[]={
			_T("Close"),
			_T("keep-alive"),
			_T("Unknow"),
	};
	class CHTTPHeaderProxConnection
		:public CHTTPHeaderLine
	{	
	public:		
		static const TCHAR *ConnectionTypeStr[];
		static BOOL Match(const CString &sHeaerName)
		{
			return StrCmpI(sHeaerName,_T("Proxy-Connection"))==0;
		}		

		CHTTPHeaderProxConnection(ConnectionType t)
			:CHTTPHeaderLine(_T("Proxy-Connection"),CTToStr(t))
			,m_ct(t)
		{}
		CHTTPHeaderProxConnection(const CString &sCT)
			:CHTTPHeaderLine(_T("Proxy-Connection"),sCT)
			,m_ct(StrToCT(sCT))
		{}
		CHTTPHeaderProxConnection(const CHTTPHeaderLine &other)
			:CHTTPHeaderLine(other)
			,m_ct(StrToCT(other.Content()))
		{}

		ConnectionType GetConnection() const
		{
			return StrToCT(m_sContent);
		}

		void SetConnection(ConnectionType t)
		{			
			m_sContent=CTToStr(t);
		}
	private:
		static ConnectionType StrToCT(LPCTSTR s)
		{
			if(StrCmpI(s,ConnectionTypeStr[CT_Close])==0)
				return CT_Close;
			if(StrCmpI(s,ConnectionTypeStr[CT_Keep_Alive])==0)
				return CT_Keep_Alive;
			ATLASSERT(0);
			return CT_Unknow;
		}

		static LPCTSTR CTToStr(ConnectionType ct)
		{
			switch(ct)
			{
			case CT_Close:
				return ConnectionTypeStr[CT_Close];
			case CT_Keep_Alive:
				return ConnectionTypeStr[CT_Keep_Alive];
			default:
				ATLASSERT(0);
				return ConnectionTypeStr[CT_Unknow]; 
			}
		}
		ConnectionType m_ct;
	};
	__declspec(selectany)
		const TCHAR *CHTTPHeaderProxConnection::ConnectionTypeStr[]={
			_T("Close"),
			_T("keep-alive"),
			_T("Unknow"),
	};
	class CHTTPHeaderContentLength
		:public CHTTPHeaderLine
	{
	public:
		static BOOL Match(const CString &sHeaerName)
		{
			return StrCmpI(sHeaerName,_T("Content-Length"))==0;
		}

		CHTTPHeaderContentLength(const CString &sContentLength)
			:CHTTPHeaderLine(_T("Content-Length"),sContentLength)
		{			
			for(int i=0;i<sContentLength.GetLength();i++)
			{
				ATLASSERT(iswdigit(sContentLength[i]));
			}
		}

		CHTTPHeaderContentLength(const CHTTPHeaderLine &other)
			:CHTTPHeaderLine(other)
		{}

		ULONG GetContentLength() const
		{
			return (ULONG)_ttoi(m_sContent);
		}

		void SetContentLength(ULONG l)
		{
			m_sContent.Format(_T("%u"),l);
		}
	};
#pragma warning(pop)
}